﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKPatternSign.StairsRoomPlanSign.ModelLayer;

namespace YJKPatternSign.StairsRoomPlanSign.ControlLayer
{
	public class OutSideSignManger : IDimensionPrepare, IDimensionMake
	{
		public OutSideSignManger(StairPlanDataPacker inputData)
		{
			this.m_useData = inputData;
		}

		public void PrepareDimension()
		{
			this.MakeDrawBoundLine(this.m_useData, false);
			this.MakeLstGrids(this.m_useData);
			this.PrepareWallElementPacker();
			this.PrepareOutSideSignData();
		}

		public bool TryMakeSign(Autodesk.Revit.DB.Document inputDoc, ViewPlan useView)
		{
			bool flag = true;
			foreach (OutSideDimensionPacker outSideDimensionPacker in this.m_lstAllDimensionPacker)
			{
				try
				{
					outSideDimensionPacker.TryMakeSign(this.m_useData.M_doc, this.m_useData.UseView);
					if (outSideDimensionPacker.GridDimension != null)
					{
						RevitDimensionExtension.ResetDimTextPos(outSideDimensionPacker.GridDimension, this.m_dViewScale);
					}
					if (outSideDimensionPacker.DetailDimension != null)
					{
						RevitDimensionExtension.ResetDimTextPos(outSideDimensionPacker.DetailDimension, this.m_dViewScale);
					}
					DimensionType dimensionType = outSideDimensionPacker.DetailDimension.DimensionType;
					double num = (double)outSideDimensionPacker.DetailDimension.Document.ActiveView.Scale;
					double num2 = dimensionType.GetParameter(BuiltInParameter.TEXT_WIDTH_SCALE).AsDouble();
					double num3 = dimensionType.GetParameter(BuiltInParameter.TEXT_SIZE).AsDouble() * num;
				}
				catch (Exception)
				{
					flag = (flag && false);
				}
			}
			return flag;
		}

		private void PrepareOutSideSignData()
		{
			List<OutSideDimensionPacker> list = new List<OutSideDimensionPacker>();
			int num = 0;
			double useLength = this.m_nowUseMax.DistanceTo(this.m_nowUseMin);
			foreach (XYZ useDriection in this.m_lstBoundingDriections)
			{
				List<WallElementPacker> list2 = new List<WallElementPacker>();
				List<ReferencePacker> list3 = new List<ReferencePacker>();
				List<ReferencePacker> list4 = new List<ReferencePacker>();
				List<KeyValuePair<Curve, int>> list5 = new List<KeyValuePair<Curve, int>>();
				Line line = this.m_lstDrawBoundLine[num];
				Line line2 = line.Clone() as Line;
				line2.MakeUnbound();
				XYZ averticalVector = Utility.GetAVerticalVector(line.Direction, false);
				if (num % 2 == 0)
				{
					list5.AddRange(this.m_lstGrids[0]);
				}
				else
				{
					list5.AddRange(this.m_lstGrids[1]);
				}
				foreach (KeyValuePair<Curve, int> keyValuePair in list5)
				{
					Line line3 = keyValuePair.Key as Line;
					if (null != line3)
					{
						XYZ xyzpoint = line2.Project(line3.GetEndPoint(0)).XYZPoint;
						list4.Add(new ReferencePacker(xyzpoint, averticalVector, null));
					}
				}
				list4 = (from k in list4
				orderby k.UsePoint.DistanceTo(this.m_nowUseMin)
				select k).ToList<ReferencePacker>();
				foreach (WallElementPacker wallElementPacker in this.m_lstAllWallElementPacker)
				{
					if (wallElementPacker.IfThisWallIsAtDriectionEnd(useDriection, useLength, this.m_ddrectionTolerance, this.m_lstAllWallElementPacker))
					{
						list2.Add(wallElementPacker);
					}
				}
				foreach (WallElementPacker wallElementPacker2 in list2)
				{
					foreach (XYZ xyz in wallElementPacker2.MakeAllDimisionPointOneMidCurve(line.Direction, this.m_ddrectionTolerance))
					{
						XYZ xyzpoint = line2.Project(xyz).XYZPoint;
						list3.Add(new ReferencePacker(xyzpoint, averticalVector, xyz));
					}
				}
				list3.AddRange(list4);
				list3 = (from k in list3
				orderby k.UsePoint.DistanceTo(this.m_nowUseMin)
				select k).ToList<ReferencePacker>();
				list.Add(new OutSideDimensionPacker(list3, list4, line, (DriectionEnum)num));
				num++;
			}
			this.m_lstAllDimensionPacker = list;
		}

		private bool IfIsBoxDriection(XYZ input)
		{
			bool result = false;
			foreach (XYZ xyz in this.m_lstBoundingDriections)
			{
				if (input.IsAlmostEqualTo(xyz, this.m_ddrectionTolerance))
				{
					result = true;
					break;
				}
			}
			return result;
		}

		private void PrepareWallElementPacker()
		{
			this.m_lstAllWallElementPacker = this.m_useData.LstAllWallElementPacker;
			for (int i = 0; i < this.m_lstAllWallElementPacker.Count; i++)
			{
				WallElementPacker wallElementPacker = this.m_lstAllWallElementPacker[i];
				if (!(wallElementPacker.UseMidCurve is Line))
				{
					wallElementPacker.ThisWallIntersectionKind = WallDriectionKindEnum.Other;
				}
				else if (!this.IfIsBoxDriection((wallElementPacker.UseMidCurve as Line).Direction.Normalize()))
				{
					wallElementPacker.ThisWallIntersectionKind = WallDriectionKindEnum.Other;
				}
				else
				{
					wallElementPacker.ThisWallIntersectionKind = WallDriectionKindEnum.Normal;
				}
			}
			for (int j = 0; j < this.m_lstAllWallElementPacker.Count; j++)
			{
				WallElementPacker wallElementPacker = this.m_lstAllWallElementPacker[j];
				for (int k = j + 1; k < this.m_lstAllWallElementPacker.Count; k++)
				{
					WallElementPacker wallElementPacker2 = this.m_lstAllWallElementPacker[k];
					if (wallElementPacker.IfInputWallIntersectionWithThis(wallElementPacker2))
					{
						wallElementPacker.AddOneIntersectionWall(wallElementPacker2);
						wallElementPacker2.AddOneIntersectionWall(wallElementPacker);
					}
				}
			}
		}

		private void MakeLstGrids(StairPlanDataPacker inputData)
		{
			this.m_lstGrids = new List<List<KeyValuePair<Curve, int>>>();
			List<KeyValuePair<Curve, int>> list = new List<KeyValuePair<Curve, int>>();
			List<KeyValuePair<Curve, int>> list2 = new List<KeyValuePair<Curve, int>>();
			Transform transform = null;
			foreach (KeyValuePair<Grid, int> keyValuePair in inputData.LstGrids)
			{
				Grid key = keyValuePair.Key;
				int value = keyValuePair.Value;
				if (-1 != keyValuePair.Value)
				{
					RevitLinkInstance revitLinkInstance = SignManger.Doc.GetElement(new ElementId(keyValuePair.Value)) as RevitLinkInstance;
					if (revitLinkInstance != null)
					{
						transform = revitLinkInstance.GetTotalTransform();
					}
				}
				if (key != null && key.Curve is Line)
				{
					Line line = key.Curve as Line;
					if (transform != null)
					{
						line = (line.CreateTransformed(transform) as Line);
					}
					if (line.Direction.Normalize().IsAlmostEqualTo(this.m_lstBoundingDriections[0], this.m_ddrectionTolerance) || line.Direction.Normalize().IsAlmostEqualTo(this.m_lstBoundingDriections[2], this.m_ddrectionTolerance))
					{
						list.Add(new KeyValuePair<Curve, int>(line, value));
					}
					else if (line.Direction.Normalize().IsAlmostEqualTo(this.m_lstBoundingDriections[1], this.m_ddrectionTolerance) || line.Direction.Normalize().IsAlmostEqualTo(this.m_lstBoundingDriections[3], this.m_ddrectionTolerance))
					{
						list2.Add(new KeyValuePair<Curve, int>(line, value));
					}
				}
			}
			list = (from k in list
			orderby Utility.PointToLineMindDistance(this.m_nowUseMin, k.Key as Line)
			select k).ToList<KeyValuePair<Curve, int>>();
			list2 = (from k in list2
			orderby Utility.PointToLineMindDistance(this.m_nowUseMin, k.Key as Line)
			select k).ToList<KeyValuePair<Curve, int>>();
			this.m_lstGrids.Add(list);
			this.m_lstGrids.Add(list2);
		}

		private void MakeDrawBoundLine(StairPlanDataPacker inputData, bool ifChangeBound = false)
		{
			ViewPlan useView = inputData.UseView;
			BoundingBoxXYZ inputBoundingBox = useView.get_BoundingBox(useView);
			this.m_duseZ = inputData.NowViewZ;
			this.m_boundIngBoxPacker = new BoundingBoxPakcer(inputBoundingBox, this.m_duseZ, inputData.LstDriections);
			if (ifChangeBound)
			{
				double moveValue = Utility.MMToFeet(StaticResource.DistanceOfBoundingBoxToDrawBox, true);
				this.m_boundIngBoxPacker.moveBound(moveValue);
			}
			this.m_nowUseMax = this.m_boundIngBoxPacker.LstPoint[2];
			this.m_nowUseMin = this.m_boundIngBoxPacker.LstPoint[0];
			this.m_lstDrawBoundLine = this.m_boundIngBoxPacker.LstBoundLine;
			this.m_lstBoundingDriections = new List<XYZ>();
			this.m_lstBoundingDriections.Add(-inputData.LstDriections[0].Normalize());
			this.m_lstBoundingDriections.Add(inputData.LstDriections[1].Normalize());
			this.m_lstBoundingDriections.Add(inputData.LstDriections[0].Normalize());
			this.m_lstBoundingDriections.Add(-inputData.LstDriections[1].Normalize());
		}

		private void createModelCurves(Autodesk.Revit.DB.Document doc, CurveLoop cvLoop)
		{
			List<Curve> list = cvLoop.Cast<Curve>().ToList<Curve>();
			new CurveArray();
			Transaction transaction = new Transaction(doc, "CreateModelCurves");
			try
			{
				transaction.Start();
				foreach (Curve curve in list)
				{
					doc.CreatYJKDetailCurve(curve);
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		private List<Line> m_lstDrawBoundLine;

		private XYZ m_nowUseMax;

		private XYZ m_nowUseMin;

		private BoundingBoxPakcer m_boundIngBoxPacker;

		private double m_duseZ;

		private double m_ddrectionTolerance = 0.05;

		private double m_dViewScale = 50.0;

		private List<XYZ> m_lstBoundingDriections = new List<XYZ>();

		private List<List<KeyValuePair<Curve, int>>> m_lstGrids;

		private List<WallElementPacker> m_lstAllWallElementPacker;

		private StairPlanDataPacker m_useData;

		private List<OutSideDimensionPacker> m_lstAllDimensionPacker;
	}
}
